#pragma once
#include "Thread.hpp"
#include "Log.hpp"
#include "LockGuard.hpp"
#include <queue>

namespace zhong
{

    class ThreadData
    {
    public:
        ThreadData(const std::string &name) : _threadname(name)
        {
        }
        ~ThreadData()
        {
        }

    public:
        std::string _threadname;
    };

    template <class T>
    class ThreadPool
    {
    private:
        ThreadPool(size_t thread_num = 5)
            : _thread_num(thread_num)
        {
            pthread_mutex_init(&_mutex, nullptr);
            // pthread_mutex_init(&_new_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);

            for (size_t i = 0; i < _thread_num; i++)
            {
                std::string threadname = "thread-";
                threadname += std::to_string(i + 1);
                ThreadData td(threadname);

                zhong::Thread<ThreadData> t(bind(&ThreadPool<T>::ThreadRun, this, td), td);
                _threads.push_back(t);
            }
        }
        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mutex);
            // pthread_mutex_destroy(&_new_mutex);
            pthread_cond_destroy(&_cond);
        }
        ThreadPool(const ThreadPool<T> &TP) = delete;
        ThreadPool<T> &operator=(const ThreadPool<T> &TP) = delete;

    public:
        static ThreadPool<T> *GetInstance()
        {
            if (_instance == nullptr)
            {
                LockGuard guard(&_instance_mutex);
                if (_instance == nullptr)
                {
                    _instance = new ThreadPool<T>();
                }
            }
            return _instance;
        }

        void ThreadRun(ThreadData &td)
        {
            while (1)
            {

                // T类型本质就是Task
                T task;
                // 获取任务
                {
                    LockGuard guard(&_mutex);
                    // 线程的动态控制
                    while (_queue.empty()) // 队列为空时，多个线程轮询判断等待
                    {
                        ThreadWait();
                    }
                    task = _queue.front();
                    _queue.pop();
                }
                // log.LogMessage(Debug, "the task is: %s\n", task.PrintTask().c_str());
                // 处理任务
                task();
                // log.LogMessage(Debug, "the task result is: %s\n", task.PrintResult().c_str());
            }
        }

        bool Start()
        {
            // log.LogMessage(Info, "the thread pool is starting\n");
            for (auto &thread : _threads)
            {
                thread.Start();
            }
            return true;
        }

        void Push(const T &in)
        {
            LockGuard guard(&_mutex);
            _queue.push(in);
            // 插入任务后可做唤醒线程了！
            ThreadWake();
        }
        bool Wait()
        {
            for (auto &thread : _threads)
            {
                thread.Join();
            }
            return true;
        }
        // 阻塞线程
        void ThreadWait()
        {
            // log.LogMessage(Info, "the thread is blocking\n");
            pthread_cond_wait(&_cond, &_mutex);
        }
        // 唤醒线程
        void ThreadWake()
        {
            // log.LogMessage(Info, "the thread is wake up\n");
            pthread_cond_signal(&_cond);
        }

    private:
        // 线程池中的任务队列
        std::queue<T> _queue;
        // 存放线程的vector
        std::vector<zhong::Thread<ThreadData>> _threads;

        // 锁与信号
        pthread_mutex_t _mutex;
        // pthread_mutex_t _new_mutex;
        pthread_cond_t _cond;

        // 任务量
        size_t _task_num;
        // 线程数
        size_t _thread_num;

        // 单例---懒汉模式
        static ThreadPool<T> *_instance;
        static pthread_mutex_t _instance_mutex;
    };
    // 静态对象
    template <class T>
    ThreadPool<T> *ThreadPool<T>::_instance = nullptr;
    template <class T>
    pthread_mutex_t ThreadPool<T>::_instance_mutex = PTHREAD_MUTEX_INITIALIZER;
}